package com.lemurian.bankdata.lite.utils;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRCsvExporterParameter;

import org.owasp.esapi.ESAPI;
import org.owasp.esapi.errors.EncryptionException;

import com.lemurian.bankdata.lite.authentication.BankDataPrincipal;
import com.lemurian.bankdata.lite.logger.BankDataLogger;
import com.lemurian.entity.Menu;

public class GlobalFunction {
	private static BankDataLogger log = BankDataLogger.getLogger(GlobalFunction.class.getSimpleName());

    private static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static Random rnd = new Random();
    private static String numbers[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

    public static String randomString(int len) {
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            sb.append(AB.charAt(rnd.nextInt(AB.length())));
        }
        return sb.toString();
    }

    public static String createPassKey() {
        String array[] = numbers;
        String pswd = "";
        for (int i = 0; i < 6; i++) {
            double rndm = Math.random() * array.length;
            int rnd1 = (int) rndm;
            pswd += array[(rnd1)];
        }
        return pswd;
    }

    public static String encodeId(Object paramId) {
        String id = String.valueOf(paramId);
        try {
            id = URLEncoder.encode(ESAPI.encryptor().encrypt(id), "UTF-8");
        } catch (EncryptionException ex) {
            log.info("CANNOT ENCRYPT ID" + ex.getMessage());
        } catch (UnsupportedEncodingException ex) {
            log.info("ENCODING IS NOT ACCEPTED : " + ex.getMessage());
        }
        return id;
    }

    public static String decodeId(Object paramId) {
        return GlobalFunction.decodeId(paramId, false);
    }

    public static String decodeId(Object paramId, Boolean decode) {
        String id = String.valueOf(paramId);
        try {
            if (decode) {
                log.sInfo(":: DECODING [%s] INTO [%s]. THEN DECRYPT IT.", id, URLDecoder.decode(id, "UTF-8"));
                id = ESAPI.encryptor().decrypt(URLDecoder.decode(id, "UTF-8").trim().replace(" ", "+"));
            } else {
                id = ESAPI.encryptor().decrypt(id.trim().replace(" ", "+"));
            }
            log.sInfo(":: DECRYPT [%s] INTO [%s]", paramId, id);
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
            log.info("ENCODING IS NOT ACCEPTED : " + ex.getMessage());
        } catch (EncryptionException ex) {
            ex.printStackTrace();
            log.info("CANNOT DECRYPT ID : " + ex.getMessage());
        }
        return id;
    }
    
    public static String encodeParameter(Object paramid) {
        StringUtils stringUtils = new StringUtils();

        String id = String.valueOf(paramid);

        try {
            id = stringUtils.encodeBase64(id);
        } catch (Exception e) {
            log.info("Error id encryption " + e.getMessage());
            e.printStackTrace();
        }

        return id;
    }

    public static String decodeParameter(Object paramid) {
        StringUtils stringUtils = new StringUtils();

        String id = String.valueOf(paramid);

        try {
            id = stringUtils.decodeBase64(id);
        } catch (Exception e) {
            log.info("Error id decryption " + e.getMessage());
            e.printStackTrace();
        }

        return id;
    }

    public static Menu getActiveMenu(BankDataPrincipal principal, String menuAction) throws Throwable {
        try {
        	
            List<Menu> menus = principal.getListMenu();
            String url = null;
            
            for (Menu m : menus) {
                if(m.getUrl() != null) {
                	
                	url = m.getUrl().trim().replaceAll(".do", "").replaceAll("/", "");
                	menuAction = menuAction.trim().replaceAll(".do", "");
                	
                    if (url.equalsIgnoreCase(menuAction)) {
                    	
                    	if(m.getParent() != null && m.getParent().getParent() != null) {
                    		m = m.getParent().getParent();
                    	} else if (m.getParent() != null) {
                    		m = m.getParent();
                    	}
                    	
                        return m;
                    }
                }
            }
            
        } catch (Throwable th) {
            throw th;
        }
        return null;
    }

    public static Date passwordValidDate(Date oldValidDate) {
        Date validDate = new Date(oldValidDate.getTime());

        Calendar validTime = Calendar.getInstance();
        validTime.setTime(validDate);
        validTime.add(Calendar.DATE, 90);

        validDate = validTime.getTime();

        return validDate;
    }

    public static int sisaHari(Date start, Date end) {
        int hari = 0;

        Calendar calendarTime1 = Calendar.getInstance();
        Calendar calendarTime2 = Calendar.getInstance();

        calendarTime1.setTime(end);
        calendarTime1.set(Calendar.AM_PM, 0);
        calendarTime1.set(Calendar.HOUR, 0);
        calendarTime1.set(Calendar.MINUTE, 0);
        calendarTime1.set(Calendar.SECOND, 0);
        calendarTime1.set(Calendar.MILLISECOND, 0);

        calendarTime2.setTime(start);
        calendarTime2.set(Calendar.AM_PM, 0);
        calendarTime2.set(Calendar.HOUR, 0);
        calendarTime2.set(Calendar.MINUTE, 0);
        calendarTime2.set(Calendar.SECOND, 0);
        calendarTime2.set(Calendar.MILLISECOND, 0);

        long differentTime = calendarTime1.getTime().getTime() - calendarTime2.getTime().getTime();

        hari = new Double(differentTime / (24 * 60 * 60 * 1000)).intValue();

        return hari;
    }

    public static byte[] exportReportToBytes(JasperPrint jasperPrint, JRExporter exporter) throws JRException {
        byte[] output;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);
        exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, ",");
        exporter.exportReport();
        output = baos.toByteArray();

        return output;
    }
}